package com.sunlee.common.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sunlee.common.core.constant.Constant;
import com.sunlee.common.core.entity.PageData;
import com.sunlee.common.core.redis.RedisKeys;
import com.sunlee.common.core.redis.RedisUtils;
import com.sunlee.common.core.utils.ConvertUtils;
import com.sunlee.common.core.utils.CustomizePageUtil;
import com.sunlee.common.core.utils.TimeUtils;
import com.sunlee.common.core.utils.TreeUtils;
import com.sunlee.common.service.dao.CategoryDao;
import com.sunlee.common.service.dto.CategoryDTO;
import com.sunlee.common.service.dto.ProductActionDTO;
import com.sunlee.common.service.dto.ProductDTO;
import com.sunlee.common.service.dto.req.CategoryProductDTO;
import com.sunlee.common.service.entity.CategoryEntity;
import com.sunlee.common.service.entity.ProductEntity;
import com.sunlee.common.service.entity.vo.CategoryVO;
import com.sunlee.common.service.service.CategoryService;
import com.sunlee.common.service.service.UserActionService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 分类表
 *
 * @author sunlee
 */
@Service
public class CategoryServiceImpl extends CrudServiceImpl<CategoryDao, CategoryEntity, CategoryDTO> implements CategoryService {

    @Autowired
    private UserActionService userActionService;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public PageData<CategoryDTO> pageOwn(Map<String, Object> params) {
        // 查询所有分类
        List<CategoryEntity> allEntityList = baseDao.selectList(getWrapper(params));

        // 补全父分类
        addParentCategory(allEntityList);

        //转为树形结构
        List<CategoryDTO> allDtoList = ConvertUtils.sourceToTarget(allEntityList, CategoryDTO.class);
        List<CategoryDTO> treeDtoList = TreeUtils.build(allDtoList, Constant.MENU_ROOT);

        //分页参数
        Long curPage = Long.parseLong((String) params.get(Constant.PAGE));
        Long limit = Long.parseLong((String) params.get(Constant.LIMIT));
        //构建分页
        return CustomizePageUtil.startPage(treeDtoList, curPage, limit);
    }

    /**
     * 补全父分类
     */
    private void addParentCategory(List<CategoryEntity> allDtoList) {
        // 子类所需的父分类Id
        Set<Long> pId = allDtoList.stream()
                .filter(item -> item.getLevel() == 2)
                .map(CategoryEntity::getPid)
                .collect(Collectors.toSet());

        // 已有的父分类Id
        Set<Long> existPid = allDtoList.stream()
                .filter(item -> item.getLevel() == 1)
                .map(CategoryEntity::getId)
                .collect(Collectors.toSet());

        pId.removeAll(existPid);

        if (CollectionUtils.isEmpty(pId)) {
            return;
        }

        // 查询对应父分类
        List<CategoryEntity> newParentCategoryList = list(new LambdaQueryWrapper<CategoryEntity>()
                .in(CategoryEntity::getId, pId));

        allDtoList.addAll(newParentCategoryList);
    }

    @Override
    public LambdaQueryWrapper<CategoryEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");
        String name = (String) params.get("name");
        String status = (String) params.get("status");

        return new LambdaQueryWrapper<CategoryEntity>()
                .like(StringUtils.isNotBlank(name), CategoryEntity::getName, name)
                .eq(StringUtils.isNotBlank(id), CategoryEntity::getName, id)
                .eq(StringUtils.isNotBlank(status), CategoryEntity::getStatus, status)
                .orderByAsc(CategoryEntity::getSort);
    }

    @Override
    public List<CategoryDTO> getAllCategoryList(Integer level) {
        List<CategoryEntity> menuList = baseDao.getAllCategoryList(level);

        List<CategoryDTO> dtoList = ConvertUtils.sourceToTarget(menuList, CategoryDTO.class);

        return TreeUtils.build(dtoList, Constant.MENU_ROOT);
    }

    @Override
    public List<CategoryVO> getValidCategoryList() {
        List<CategoryVO> result = redisUtils.get(RedisKeys.APP_CATEGORY_LIST_KEY);

        if (Objects.nonNull(result)) {
            return result;
        }
        List<CategoryVO> categoryList = baseDao.getValidCategoryList();

        result = TreeUtils.build(categoryList, Constant.MENU_ROOT);

        redisUtils.set(RedisKeys.APP_CATEGORY_LIST_KEY, result, TimeUtils.NUM_12, TimeUnit.HOURS);
        return result;
    }


    @Override
    public PageData<ProductDTO> getCategoryByIdAndLevel(CategoryProductDTO request) {

        Page<ProductEntity> page = new Page<>(request.getPage(), request.getLimit());
        IPage<ProductEntity> pageResult = baseDao.getCategoryByIdAndLevel(page, request);
        if (CollectionUtils.isEmpty(pageResult.getRecords())) {
            return null;
        }

//        ListPageUtil<ProductEntity> productEntityListPage = new ListPageUtil<>(productEntityList, request.getPage(), request.getLimit());
        List<ProductDTO> productDtoS = ConvertUtils.sourceToTarget(pageResult.getRecords(), ProductDTO.class);

        // 设置下载、浏览、收藏数
        if (!CollectionUtils.isEmpty(productDtoS)) {
            List<Long> pIds = productDtoS.stream().map(ProductDTO::getId).collect(Collectors.toList());
            Map<Long, ProductActionDTO> productMap = userActionService.getProductActionDataByIds(pIds);
            for (ProductDTO item : productDtoS) {
                item.setActionData(productMap.get(item.getId()));
            }
        }

        return new PageData<>(productDtoS, pageResult.getTotal());
    }

    @Override
    public List<CategoryEntity> list(LambdaQueryWrapper<CategoryEntity> wrapper) {
        return baseDao.selectList(wrapper);
    }

    @Override
    public void cleanCacheAllCategory() {
        redisUtils.delete(RedisKeys.APP_CATEGORY_LIST_KEY);
    }

    @Override
    public CategoryDTO getOwn(Long id) {
        return ConvertUtils.sourceToTarget(baseDao.getById(id), CategoryDTO.class);
    }

    @Override
    public List<CategoryEntity> existSubCategory(Long[] ids) {
        return baseDao.existSubCategory(ids);
    }
}